package com.iqiyi.pps.epg.core.service.program;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.iqiyi.kiwi.utils.Configuration;
import com.iqiyi.pps.epg.api.model.web.program.*;
import com.iqiyi.pps.epg.api.model.web.query.TFilter;
import com.iqiyi.pps.epg.api.model.web.query.TPage;
import com.iqiyi.pps.epg.core.dao.base.Page;
import com.iqiyi.pps.epg.core.dao.base.PropertyFilter;
import com.iqiyi.pps.epg.core.dao.program.*;
import com.iqiyi.pps.epg.core.model.channel.ChannelBase;
import com.iqiyi.pps.epg.core.model.channel.ChannelConfig;
import com.iqiyi.pps.epg.core.model.program.*;
import com.iqiyi.pps.epg.core.rpc.qipu.QipuService;
import com.iqiyi.pps.epg.core.service.channel.ChannelService;
import com.iqiyi.pps.epg.core.service.notifymail.NotifyMailService;
import com.iqiyi.pps.epg.core.utils.*;
import com.iqiyi.pps.epg.core.utils.mail.MailConstant;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.*;
import org.hibernate.type.LongType;
import org.hibernate.type.StringType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by karkarrotxu on 2014/12/1.
 */
@Service
@Transactional
public class ProgramServiceImpl implements ProgramService {
    private static String[] SYSTEM_USRS = {"system", "_system_", "0"};
    private static String FORMAT_SORT_LOG = "before:[start=%d][end=%d] ; after:[start=%s][end=%s]";
    protected Logger logger = LoggerFactory.getLogger(ProgramServiceImpl.class);
    @Autowired
    private ProgramDataDao programDataDao;
    @Autowired
    private IProgramDirectorService programDirectorService;
    @Autowired
    private IqiyiOADataDao oaDataDao;
    @Autowired
    private FeedDataDao feedDataDao;

    @Autowired
    private ProgramLogDao programLogDao;
    @Autowired
    private ProgramDataBaseDao programDataBaseDao;
    @Autowired
    private ProgramAdvertDao programAdvertDao;
    @Autowired
    private QipuService qipuService;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private ProgramDataExpiredDao programDataExpiredDao;
    @Autowired
    private IProgramAsyncService programAsyncService;
    @Autowired
    private NotifyMailService notifyMailService;
    @Autowired
    private SnapshotTaskDataDao snapshotTaskDataDao;


    private int skipTestFlag = 0;
    private long skipLastCacheTime = 0;

    public void doSyncById(long id) {
        programAsyncService.addAsyncById(id);
    }

    public static boolean isProductionEnv() {
        return "production".equals(Configuration.getString("deploy.env"));
    }

    private boolean getSkipTestFlag() {
        long curTime = System.currentTimeMillis();
        if (skipLastCacheTime < curTime) {
            synchronized (this) {
                ChannelConfig channelConfig = channelService.getConfigData("skip_test_stm", 1);
                if (null != channelConfig) {
                    skipTestFlag = Integer.valueOf(channelConfig.getVal());
                }
            }
            skipLastCacheTime = curTime + DateTimeUtil.MINUTE_TIME;
        }
        return skipTestFlag == 1;
    }

    public void doSyncByFatherId(long fatherId) {
        qipuService.syncProgramDataByFatherId(fatherId);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public boolean checkInRange(int fatherId, String startTime, String endTime, long excludeId) {
        String hql = "select count(id) from ProgramData where fatherId =? and deleteFlag = 0 and  startPlayTime < timestamp(?) and stopPlayTime > timestamp(?) and id != ?";
        long resultNum = (Long) (programDataDao.createQuery(hql)
                .setInteger(0, fatherId)
                .setString(1, endTime)
                .setString(2, startTime).setLong(3, excludeId)
                .uniqueResult());
        return resultNum > 0;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramData> getByDay(String day, int fatherId) {
        return getBetweenDays(day, day, fatherId, false);
    }


    public List<ProgramData> getBetweenDays(String startDay, String endDay) {
        return getBetweenDays(startDay, endDay, -1, false);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void saveProgramDataList(List<ProgramData> saveList, long channelId) {
        int addLength = saveList.size();
        if (addLength > 0) {
            logger.info("[dealResponseList]  start fill qipuId");
            List<Long> qipuIdList = qipuService.registerQipuId(23, addLength);
            ProgramData entity = null;
            ChannelBase tempBase = channelService.getChannelBase(channelId);
            String formatString = getFormatString(tempBase);
            for (int i = 0; i < addLength; i++) {
                entity = saveList.get(i);
                if (entity.checkIsIllegal()) {
                    continue;
                }
                entity.setQipuId(qipuIdList.get(i));
                if (formatString != null) {
                    entity.setPageUrl(String.format(formatString, UrlGeneratorUtil.generateUrl(entity.getQipuId())));
                }
            }
            logger.info("[dealResponseList]  end fill qipuId");
        }

        /*保存 记录 */
        Session session = programDataDao.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();
        try {
            for (ProgramData temp : saveList) {
                session.save(temp);
            }
            transaction.commit();
        } catch (Exception e) {
            logger.error(e.getMessage());
            transaction.rollback();
        } finally {
            session.close();
        }

        /* 绑定 播控*/
        //     for (ProgramData temp : saveList) {
        //         programAsyncService.addBroadCoastToQipu(temp, false);
        //    }
        programAsyncService.triggerOnce();
    }

    private String getFormatString(ChannelBase tempBase) {
        String formatString = null;
        if (tempBase.getLiveType() == 2) {
            formatString = "http://www.iqiyi.com/l_%s.html";
        } else if (tempBase.getLiveType() == 1 || tempBase.getLiveType() == 3) {
            if (tempBase.getPageUrl() != null && tempBase.getPageUrl().startsWith("http")) {
                formatString = tempBase.getPageUrl() + "?l=%s";
            } else {
                formatString = UrlGeneratorUtil.getChannelPageUrl(tempBase.getQipuId(), tempBase.getLiveType()) + "?l=%s";
            }
        }
        return formatString;
    }

    @Override
    public long saveProgramData(ProgramData programData) {
        ChannelBase tempBase = channelService.getChannelBase(programData.getFatherId());
        String formatString = getFormatString(tempBase);
        if (formatString != null) {
            programData.setPageUrl(String.format(formatString, UrlGeneratorUtil.generateUrl(programData.getQipuId())));
        }
        programDataDao.saveOnly(programData);
        return programData.getId();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void updateFlagProgramDataList(List<ProgramData> updateList) {
        Session session = programDataDao.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();
        try {
            for (ProgramData tempData : updateList) {
                tempData.setSync(0);
                session.update(tempData);
            }
            transaction.commit();
        } catch (Exception e) {
            logger.error(e.getMessage());
            transaction.rollback();
        } finally {
            session.close();
        }
    }

    @Override
    public void deleteFlagProgramDataListByFatherId(long fatherId) {
        String hql = "update ProgramData set deleteFlag = 1,sync = 0 where fatherId = ? and deleteFlag != 1";
        int executeUpdate = programDataDao.createQuery(hql)
                .setParameter(0, (int) fatherId)
                .executeUpdate();
        logger.debug("[deleteFlagProgramDataListByFatherId] executeUpdate:" + executeUpdate + " fatherId:" + fatherId);
    }

    @Override
    public int deleteFlagProgramDataListById(List<Long> idList) {
        if (idList.size() == 0) {
            return 0;
        }
        String ids = idList.toString();
        String hql = "update ProgramData set deleteFlag = 1,sync = 0 where deleteFlag != 1 and id in (" + ids.substring(1, ids.length() - 1) + ")";
        int executeUpdate = programDataDao.createQuery(hql).executeUpdate();
        logger.debug("[deleteFlagProgramDataListById] executeUpdate:" + executeUpdate + " idLength:" + idList.size());
        return executeUpdate;
    }

    @Override
    public void deleteFlagProgramDataList(List<ProgramData> deleteList) {
        List<Long> idList = new ArrayList<Long>();
        for (ProgramData tempData : deleteList) {
            idList.add(tempData.getId());
        }
        deleteFlagProgramDataListById(idList);

    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramData> findByQipuIds(List<Long> idList) {
        List<ProgramData> retList = null;
        if (idList.size() > 0) {
            Criteria c = programDataDao.createCriteria();
            c.addOrder(Order.asc("startPlayTime"));
            c.add(Restrictions.in("qipuId", idList));
            retList = programDataDao.find(c);
            logger.info("[findByQipuIds] end " + retList.size());
        }
        return retList;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramDataBase> findDataBaseByProgramDataIds(List<Long> idList) {
        List<ProgramDataBase> retList = null;
        if (idList.size() > 0) {
            Criteria c = programDataBaseDao.createCriteria();
            c.add(Restrictions.in("fatherId", idList));
            retList = programDataBaseDao.find(c);
            logger.info("[findDataBaseByProgramDataIds] end " + retList.size());
        }
        return retList;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramDataBase> findDataBaseByProgramDataId(long programId) {
        List<ProgramDataBase> retList = null;
        Criteria c = programDataBaseDao.createCriteria();
        c.add(Restrictions.eq("fatherId", programId));
        retList = programDataBaseDao.find(c);
        logger.info("[findDataBaseByProgramDataId] end " + retList.size());
        return retList;
    }


    public List<ProgramData> getBetweenDays(String startDay, String endDay, int fatherId, boolean stripInvalid) {
        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.between("startPlayTime", Timestamp.valueOf(startDay + " 00:00:00"), Timestamp.valueOf(endDay + " 23:59:59")));
        if (fatherId > 0) {
            cList.add(Restrictions.eq("fatherId", fatherId));
        }
        if (stripInvalid) {
            cList.add(Restrictions.neProperty("startPlayTime", "stopPlayTime"));
            cList.add(Restrictions.eq("illegalStatus", 0));
        }

        cList.add(Restrictions.eq("deleteFlag", 0));
        List<Order> orderList = new ArrayList<Order>();
        orderList.add(Order.asc("startPlayTime"));
        orderList.add(Order.desc("lastSortTime"));
        orderList.add(Order.asc("id"));
        return queryDataByCriterion(cList, orderList, -1);
    }


    @Override
    public void insertProgramDataBaseList(List<ProgramDataBase> list) {
        for (ProgramDataBase temp : list) {
            programDataBaseDao.saveOnly(temp);
        }
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramData> queryDataByCriterion(List<Criterion> list, List<Order> orderList, int maxResultNum) {
        Criteria criteria = programDataDao.createCriteria();
        for (Criterion temp : list) {
            criteria.add(temp);
        }
        if (maxResultNum != -1) {
            criteria.setMaxResults(maxResultNum);
        }
        if (orderList != null && !orderList.isEmpty()) {
            for (Order order : orderList) {
                criteria.addOrder(order);
            }
        }
        return programDataDao.find(criteria);
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramDataBase> queryDataBaseByCriterion(List<Criterion> list, List<Order> orderList) {
        Criteria criteria = programDataBaseDao.createCriteria();
        for (Criterion temp : list) {
            criteria.add(temp);
        }
        if (orderList != null) {
            for (Order tempOrder : orderList) {
                criteria.addOrder(tempOrder);
            }
        }
        return programDataBaseDao.find(criteria);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ProgramData findProgramDataById(long id) {
        String hql = "from ProgramData where id = ?";
        ProgramData returnData = (ProgramData) programDataDao.createQuery(hql).setParameter(0, id).uniqueResult();
        return returnData;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ProgramData findProgramDataByQipuId(long id) {
        String hql = "from ProgramData where qipuId = ?";
        ProgramData returnData = (ProgramData) programDataDao.createQuery(hql).setParameter(0, id).uniqueResult();
        return returnData;
    }


    private List<ProgramDataBase> findProgramDataBaseByFatherId(List<Long> fatherIdList) {
        List<Criterion> cList = new ArrayList<Criterion>();
        if (fatherIdList.size() > 0) {
            cList.add(Restrictions.in("fatherId", fatherIdList));
        }
        return queryDataBaseByCriterion(cList, null);
    }


    public void deleteProgramDataBaseByFatherId(long fatherId) {
        String hql = "delete from ProgramDataBase where fatherId = ?";
        int affectNum = programDataBaseDao.batchExecute(hql, fatherId);
        logger.debug("[deleteProgramDataBaseByFatherId] affectNum :" + affectNum);
    }

    private String rebuildOrderBy(String original, String aliasName) {
        String[] params = original.split(",");
        StringBuilder sBuilder = new StringBuilder();
        for (String param : params) {
            sBuilder.append(aliasName + "." + param);
            sBuilder.append(",");
        }
        if (sBuilder.length() > 0) {
            sBuilder.deleteCharAt(sBuilder.length() - 1);
        }
        return sBuilder.toString();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public TProgramPage findTProgramChannelPage(TPage page, TFilter filter) {
        Map<String, String> map = filter.getFilters();
        String tempPattern = "${PARAMS}";
        String resultPattern = "{program.*}, {channel.*}";
        String totalPattern = "COUNT(*) as total";
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        String hql = "select " + tempPattern + " from live_episode program, channel_base channel where program.father_id = channel.id ";
        String original = page.getOrderBy();
        page.setOrderBy(rebuildOrderBy(original, "program"));
        Page<ProgramData> dbPage = TransUtil.buildPage(page);

        String sql = SqlUtil.buildWithPropertyFilter(hql, filterList);

        boolean skipQuery = false;
        if (dbPage.isAutoCount()) {
            if (!isProductionEnv()) {
                logger.debug("[build sql totalPattern]" + sql.replace(tempPattern, totalPattern));
            }
            String totalCount = programDataBaseDao.getSession().createSQLQuery(sql.replace(tempPattern, totalPattern))
                    .addScalar("total", new StringType()).list().get(0).toString();

            page.setTotalCount(Long.valueOf(totalCount));
            if (page.getTotalCount() == 0) {
                skipQuery = true;
                logger.debug("[skip query  case total is zero ]");
            }
        }
        List<ProgramData> dataList = new ArrayList<>();
        if (!skipQuery) {
            sql = SqlUtil.buildAppendPage(dbPage, sql);
            sql = SqlUtil.buildAppendPageLimit(dbPage, sql);
            if (!isProductionEnv()) {
                logger.debug("[build sql resultPattern ]" + sql.replace(tempPattern, resultPattern));
            }
            List result = programDataDao.getSession().createSQLQuery(sql.replace(tempPattern, resultPattern)).
                    addEntity("program", ProgramData.class).addEntity("channel", ChannelBase.class).list();
            for (Object single : result) {
                Object[] obj = (Object[]) single;
                ProgramData programData = (ProgramData) obj[0];
                ChannelBase channelBase = (ChannelBase) obj[1];
                programData.setChannelName(channelBase.getName());
                programData.setChannelHasStream(channelBase.getHasStream());
                programData.setChannelLiveType(channelBase.getLiveType() == null ? 0 : channelBase.getLiveType().intValue());
                programData.setFormal(channelBase.getFormal());
                if (org.apache.commons.lang3.StringUtils.isNotBlank(programData.getDaojuId())) {
                    // 渠道明星设置为无效
                    JSONObject response = ApiDaojuUtil.getStarList(programData.getDaojuId());
                    if (response == null) {
                        programData.setDaojuStar("");
                    } else {
                        JSONObject localStarList = new JSONObject();
                        String daojuStarFlag = response.getJSONObject("platform").getString("is_group");
                        JSONArray starList = response.getJSONArray("star_list");
                        localStarList.put("daojuStarFlag", daojuStarFlag);
                        localStarList.put("starList", starList);
                        programData.setDaojuStar(localStarList.toJSONString());
                    }
                }
                //获取节目导播状态
                ProgramDirector programDirector = programDirectorService.getByProgramQipuId(programData.getQipuId());
                if (programDirector != null) { //有节目正在导播
                    programData.setDirectorOpen(1);
                } else { //没有节目正在导播
                    programData.setDirectorOpen(0);
                }
                dataList.add(programData);
            }
        }


        TProgramPage programPage = new TProgramPage();
        page.setOrderBy(original);
        programPage.setTPage(page);
        List<TProgram> tProgramList = transToTProgramList(dataList, true, true);
        programPage.setResult(tProgramList);
        return programPage;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public TProgramPage findLibraryPage(TPage page, TFilter filter) {
        String tempPattern = "${PARAMS}";
        String resultPattern = " program.id,program.qipu_id,program.page_url," +
                "program.play_status,program.boss_status,program.type,program.episode_grade," +
                "program.is_delete,program.recommend_rate,program.hot,program.test," +
                "program.start_play_time,program.stop_play_time,program.update_time," +
                "channel.name,channel.formal,channel.has_stream,channel.live_type, " +
                "program.father_id,program.program_name,program.director_enable, " +
                "program.oa_doc_editor_status,program.oa_doc_url,program.oa_doc_no, "+
                "program.dbt_region";
        String totalPattern = "COUNT(*) as total";
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        String hql = "select " + tempPattern + " from live_episode program, channel_base channel where program.father_id = channel.id ";
        String original = page.getOrderBy();
        page.setOrderBy(rebuildOrderBy(original, "program"));
        Page<ProgramData> dbPage = TransUtil.buildPage(page);
        String sql = SqlUtil.buildWithPropertyFilter(hql, filterList);
        boolean skipQuery = false;
        if (dbPage.isAutoCount()) {
            if (!isProductionEnv()) {
                logger.debug("[build sql totalPattern]" + sql.replace(tempPattern, totalPattern));
            }
            String totalCount = programDataBaseDao.getSession().createSQLQuery(sql.replace(tempPattern, totalPattern))
                    .addScalar("total", new StringType()).list().get(0).toString();

            page.setTotalCount(Long.valueOf(totalCount));
            if (page.getTotalCount() == 0) {
                skipQuery = true;
                logger.debug("[skip query  case total is zero ]");
            }
        }
        List<ProgramData> dataList = new ArrayList<>();
        if (!skipQuery) {
            sql = SqlUtil.buildAppendPage(dbPage, sql);
            sql = SqlUtil.buildAppendPageLimit(dbPage, sql);
            if (!isProductionEnv()) {
                logger.debug("[build sql resultPattern ]" + sql.replace(tempPattern, resultPattern));
            }
            List result = programDataDao.getSession().createSQLQuery(sql.replace(tempPattern, resultPattern)).list();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            ProgramData programData = null;
            for (Object single : result) {
                Object[] obj = (Object[]) single;
                programData = new ProgramData();
                programData.setId(Long.valueOf("" + obj[0]));
                programData.setFatherId(Integer.valueOf("" + obj[18]));
                programData.setPname(obj[19] + "");
                programData.setQipuId(Long.valueOf("" + obj[1]));
                programData.setPageUrl(obj[2] + "");
                programData.setPlayStatus((Integer) obj[3]);
                programData.setBossStatus(obj[4] + "");
                programData.setType((Integer) obj[5]);
                programData.setEpisodeGrade((Integer) obj[6]);
                programData.setDeleteFlag(Boolean.valueOf(obj[7] + "") == Boolean.TRUE ? 1 : 0);
                programData.setRecommendRate((Integer) obj[8]);
                programData.setHot(Integer.valueOf(obj[9] + ""));
                programData.setTest(Integer.valueOf(obj[10] + ""));
                programData.setStartPlayTime(new Timestamp(DateTimeUtil.parseLongFormat(sdf.format(obj[11]))));
                programData.setStopPlayTime(new Timestamp(DateTimeUtil.parseLongFormat(sdf.format(obj[12]))));
                programData.setUpdateTime(new Timestamp(DateTimeUtil.parseLongFormat(sdf.format(obj[13]))));
                programData.setChannelName(obj[14] + "");
                programData.setFormal(Boolean.valueOf(obj[15] + "") == Boolean.TRUE ? 1 : 0);
                programData.setChannelHasStream(Boolean.valueOf(obj[16] + "") == Boolean.TRUE ? 1 : 0);
                programData.setChannelLiveType((Integer) obj[17]);
                programData.setDirectorEnable((Integer) obj[20]);
                programData.setOaDocEditorStatus((String) obj[21]);
                programData.setOaDocUrl((String) obj[22]);
                programData.setOaDocNo((String) obj[23]);
                programData.setDbtRegion((String) obj[24]);
                dataList.add(programData);
            }
        }
        TProgramPage programPage = new TProgramPage();
        page.setOrderBy(original);
        programPage.setTPage(page);
        List<TProgram> tProgramList = transToTProgramLibrary(dataList);
        programPage.setResult(tProgramList);
        return programPage;
    }

    @Override
    public void editProgramData(ProgramData programData) {
        programData.setSync(0);
        programDataDao.save(programData);
    }

    @Override
    public synchronized void editProgramDataBaseList(TProgram entity) {
        List<TProgramBase> relationList = entity.getRelationList();
        if (relationList == null) {
            relationList = new ArrayList<TProgramBase>();
        }
        deleteProgramDataBaseByFatherId(entity.getId());
        List<ProgramDataBase> insertList = new ArrayList<ProgramDataBase>();

        ProgramDataBase findOrigin = null;
        boolean isSport = entity.getType() == 1;
        for (TProgramBase tempBase : relationList) {
            if (!isSport && (tempBase.getType() == 3 || tempBase.getType() == 4)) {
                continue;
            }
            findOrigin = new ProgramDataBase();
            findOrigin.setFatherId(entity.getId());
            findOrigin.setAddTime(new Timestamp(System.currentTimeMillis()));
            findOrigin.setType(tempBase.getType());
            findOrigin.setValue(tempBase.getValue());
            findOrigin.setKey(tempBase.getKey());
            insertList.add(findOrigin);
        }
        insertProgramDataBaseList(insertList);
    }

    //  private ProgramDataBase createProgramDataBase

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public TProgram findTProgramById(long id) {

        return findTProgramById(id, true);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public TProgram findTProgramById(long id, boolean needPic) {
        ProgramData programData = findProgramDataById(id);
        TProgram tProgram = transToTProgram(programData, needPic);
        List<Long> idList = new ArrayList<Long>();
        idList.add(programData.getId());
        List<ProgramDataBase> programDataBaseList = findProgramDataBaseByFatherId(idList);
        TProgramBase _TProgramBase = null;
        for (ProgramDataBase tempBase : programDataBaseList) {
            _TProgramBase = new TProgramBase();
            _TProgramBase.setId(tempBase.getId());
            _TProgramBase.setType(tempBase.getType());
            _TProgramBase.setKey(tempBase.getKey());
            _TProgramBase.setValue(tempBase.getValue());
            tProgram.addToRelationList(_TProgramBase);
        }
        return tProgram;
    }

    @Override
    public int recoverSyncStatus() {
        //  Date searchStartTime = new Date(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10);
        String hql = "update ProgramData set sync = 0 where sync = 2 and qipuId > 0";
        int totalCount = 0;
        int executeUpdate = 0;
        do {
            executeUpdate = programDataDao.createQuery(hql).setMaxResults(60).executeUpdate();
            totalCount += executeUpdate;
        } while (executeUpdate == 60);
        logger.info("[totalCount={}]", totalCount);
        return totalCount;
    }

    @Override
    public int syncProgramDelete(String channelIds) {
        //  String minLimit = DateTimeUtil.transShortFormat( System.currentTimeMillis() - 86400000L*2) + " 00:00:00";
        //  String hql ="update ProgramData set deleteFlag = 1,sync = 0 where deleteFlag = 0 and startPlayTime >='"+minLimit+"' and fatherId in (" +channelIds.substring(1, channelIds.length() - 1) + ")";
        String hql = "update ProgramData set deleteFlag = 1,sync = 0 where deleteFlag = 0 and fatherId in (" + channelIds.substring(1, channelIds.length() - 1) + ")";
        int executeUpdate = programDataDao.createQuery(hql).executeUpdate();
        return executeUpdate;
    }

    @Override
    public int clearAutomation(long channelId, long startTime) {
        int executeUpdate = -1;
        String hql = "update ProgramData set deleteFlag = 1,sync = 0 where fatherId=" + channelId;
        String dayTime = null;
        if (startTime > 0) {
            dayTime = DateTimeUtil.transLongFormat(startTime);
            hql += " and startPlayTime >= '" + DateTimeUtil.transLongFormat(startTime) + "'";
        }
        try {
            executeUpdate = programDataDao.createQuery(hql).executeUpdate();
            logger.info("[clearAutomation]channelId={}, executeUpdate={},dayTime={}", channelId, executeUpdate, dayTime);
        } catch (Exception e) {
            logger.error("[clearAutomation] excp:", e);
        }
        return executeUpdate;
    }


    @Override
    @Transactional
    public List<TProgram> findNeedSyncTProgram(int onceNum) {
        List<TProgram> resultList = null;
        List<Criterion> cList = new ArrayList<Criterion>();
        cList.add(Restrictions.eq("sync", 0));
        cList.add(Restrictions.gt("qipuId", 0L));
        //cList.add(Restrictions.ge("startPlayTime", new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10)));
//        LogicalExpression a1 =  Restrictions.and(Restrictions.eq("type", 7), Restrictions.between("startPlayTime",new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10),
//                new Timestamp(System.currentTimeMillis() + DateTimeUtil.DAY_TIME * 3)));

        SimpleExpression tenDaysBefore = Restrictions.ge("startPlayTime", new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10));
        Criterion tenDaysBeforeAndThreeDaysAfter = Restrictions.between("startPlayTime", new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10),
                new Timestamp(System.currentTimeMillis() + DateTimeUtil.DAY_TIME * 1));
        SimpleExpression deletedProgram = Restrictions.eq("deleteFlag", 1);
        LogicalExpression undeletedProgram = Restrictions.and(Restrictions.ne("deleteFlag", 1), tenDaysBeforeAndThreeDaysAfter);
        LogicalExpression a = Restrictions.and(Restrictions.eq("type", 7), Restrictions.or(deletedProgram, undeletedProgram));

        LogicalExpression b = Restrictions.and(Restrictions.ne("type", 7), tenDaysBefore);

        SimpleExpression c = Restrictions.le("stopPlayTime", new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 20));
        cList.add(Restrictions.or(c, Restrictions.or(a, b)));

        List<Order> orderList = new ArrayList<Order>();
        orderList.add(Order.asc("startPlayTime"));
        Criteria criteria = programDataDao.createCriteria();
        for (Criterion temp : cList) {
            criteria.add(temp);
        }
        criteria.setMaxResults(onceNum);
        criteria.addOrder(Order.asc("startPlayTime"));
        List<ProgramData> dataList = programDataDao.find(criteria);

        if (dataList.size() > 0) {
            List<Long> updateList = new ArrayList<Long>();
            for (ProgramData temp : dataList) {
                updateList.add(temp.getId());
            }
            String ids = updateList.toString();
            String hql = "update ProgramData set sync = 2 where sync = 0 and id in (" + ids.substring(1, ids.length() - 1) + ")";
            int executeUpdate = programDataDao.createQuery(hql).executeUpdate();
            logger.debug("[findNeedSyncTProgram] executeUpdate:" + executeUpdate + " idLength:" + updateList.size());
        }
        resultList = transToTProgramList(dataList, false, true);
        return resultList;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public boolean hasPrograms(long fatherId) {
        List<Criterion> cList = new ArrayList<Criterion>();
        if (fatherId > 0) {
            cList.add(Restrictions.eq("fatherId", (int) fatherId));
        }
        List<ProgramData> dataList = queryDataByCriterion(cList, null, 1);
        return dataList.size() > 0;
    }

    @Override
    public String searchProgram(String name, String startDate, String endDate, String porgramQipuId, String channelQipuId, String channelName) {
        StringBuilder sql = new StringBuilder();
      /*  String sql = "SELECT {base.*}, {program.*} FROM live_episode program LEFT JOIN channel_base base ON base.id = program.father_id " +
                "WHERE program.start_play_time >= '" + startDate + "' " +"AND program.start_play_time <= '" + endDate + "' AND program.is_delete = 0 AND program.is_sync = 1 AND program.program_name LIKE '%" + name + "%' AND program.qipu_id = "+porgramQipuId+" AND base.qipu_id = "+channelQipuId+" AND base.name like '%"+channelName+"%'";
*/
        sql.append("SELECT {base.*}, {program.*} FROM live_episode program LEFT JOIN channel_base base ON base.id = program.father_id ");
        sql.append("WHERE program.start_play_time >= '" + startDate + "' AND program.start_play_time <= '" + endDate + "' AND program.is_delete = 0 AND program.qipu_id > 0 ");
        sql.append(" AND base.is_enable != -1 ");
        if (StringUtils.isNotBlank(name)) {
            sql.append(" AND program.program_name LIKE '%" + StringEscapeUtils.escapeSql(name) + "%'");
        }
        if (StringUtils.isNotBlank(channelName)) {
            sql.append(" AND base.name LIKE '%" + StringEscapeUtils.escapeSql(channelName) + "%' ");
        }
        if (StringUtils.isNotBlank(porgramQipuId)) {
            sql.append("AND program.qipu_id = " + porgramQipuId + " ");
        }
        if (StringUtils.isNotBlank(channelQipuId)) {
            sql.append(" AND base.qipu_id = " + channelQipuId + " ");
        }

        List result = programDataDao.getSession().createSQLQuery(sql.toString()).addEntity("base", ChannelBase.class).addEntity("program", ProgramData.class).list();
        Map<Long, String> referMap = new HashMap<Long, String>();
        for (Object single : result) {
            Object[] obj = (Object[]) single;
            ChannelBase channelBase = (ChannelBase) obj[0];
            referMap.put(channelBase.getId(), "");
        }
        if (referMap.size() > 0) {
            String fatherIds = referMap.keySet().toString().replaceAll("\\[|\\]|\\s", "");
            String platformsSql = "select father_id,group_concat(play_platform) platforms from platform_control where available_status = 1 and  father_id in (" + fatherIds + ") group by father_id";
            List<Object[]> platformResults = programDataDao.getSession().createSQLQuery(platformsSql).addScalar("father_id", new LongType()).addScalar("platforms", new StringType()).list();
            for (Object[] single : platformResults) {
                referMap.put((Long) single[0], (String) single[1]);
            }
        }


        List<Map<String, String>> ret = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Object single : result) {
            Object[] obj = (Object[]) single;
            ChannelBase channelBase = (ChannelBase) obj[0];
            ProgramData programData = (ProgramData) obj[1];
            if (StringUtils.isBlank(channelName) || channelBase.getName().indexOf(channelName) >= 0) {
                Map<String, String> temp = new HashMap<>();
                temp.put("qipuId", programData.getQipuId() + "");
                temp.put("name", programData.getPname());
                temp.put("startDate", sdf.format(programData.getStartPlayTime()));
                temp.put("endDate", sdf.format(programData.getStopPlayTime()));
                temp.put("channelName", channelBase.getName());
                temp.put("logo", channelBase.getDefaultLogoUrl());
                temp.put("channelQipuId", channelBase.getQipuId() + "");
                temp.put("platforms", referMap.get(channelBase.getId()));
                temp.put("type", programData.getType() + "");
                temp.put("pageUrl", programData.getPageUrl() + "");
                // add by xiaolin 2015年7月21日
                //在节目名称输入之后suggest列表添加：频道类型（卫视、地方台、中央台、境外台、爱奇艺直播台），启用状态（是、否），划价状态（免费、付费未划价、付费已划价）
                temp.put("channelType", channelBase.getType() + "");
                temp.put("channelStatus", channelBase.getIsEnable() + "");
                temp.put("VideoPayStatus", programData.getBossStatus());
                ret.add(temp);
            }
        }

        return JSON.toJSONString(ret);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramRecent> findRecent(List<Long> idList, String dateMin, String dateMax, boolean checkSync) {
        if (dateMin == null || dateMax == null || dateMin.length() < 19 || dateMax.length() < 19) {
            logger.info("[findRecent error params]" + (dateMin + "|" + dateMax));
            return null;
        }

        String ids = idList.toString();
        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append("select father_id ,count(id) countNum , DATE_FORMAT(start_play_time ,'%Y-%m-%d') checkDay from live_episode" +
                " where father_id in ( " + ids.substring(1, ids.length() - 1) + " ) and is_delete = 0 ");
        if (checkSync) {
            sqlBuffer.append(" and is_sync != 1 ");
        }

        sqlBuffer.append(" and start_play_time >='" + dateMin + "' and start_play_time<='" + dateMax + "' group by father_id, checkDay");
        List<Object[]> result = programDataDao.getSession().createSQLQuery(sqlBuffer.toString()).list();
        ProgramRecent temple = null;
        List<ProgramRecent> list = new ArrayList<ProgramRecent>();
        for (Object[] single : result) {
            temple = new ProgramRecent();
            temple.setFatherId(Long.valueOf("" + single[0]));
            temple.setCountNum(Integer.valueOf("" + single[1]));
            temple.setDate((String) single[2]);
            list.add(temple);
        }
        return list;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public void logoutNoSyncRecent(long fatherId, String dateMin, String dateMax) {
        logger.info("[logoutNoSyncRecent][cid={}][start={}][end={}]", fatherId, dateMin, dateMax);
        try {
            StringBuffer sqlBuffer = new StringBuffer();
            sqlBuffer.append("select id from live_episode where father_id = " + fatherId + " and is_sync != 1 ");
            sqlBuffer.append(" and start_play_time >='" + dateMin + "' and start_play_time<='" + dateMax + "'");
            List<Long> result = programDataDao.getSession().createSQLQuery(sqlBuffer.toString()).addScalar("id", new LongType()).list();
            if (result.size() > 0) {
                for (Long noSyncPid : result) {
                    logger.info("[logoutNoSyncRecent] [pid={}]", noSyncPid);
                }
            }
        } catch (Exception e) {
            logger.error("[logoutNoSyncRecent]", e);
        }

    }

    @Override
    public String searchFilterProgram(Map<String, String> params) {
        StringBuffer sbuffer = new StringBuffer();
        sbuffer.append("select tempA.*,tempB.platforms from (" +
                "select live_episode.qipu_id qipuId," +
                "live_episode.type, " +
                "live_episode.default_logo_url thumbnail," +
                "live_episode.program_name pname," +
                "live_episode.start_play_time startPlayTime," +
                "live_episode.stop_play_time endPlayTime," +
                "live_episode.boss_status bossStatus," +
                "channel_base.name as cname," +
                "live_episode.father_id cid, " +
                "live_episode.page_url pageUrl " +
                "from live_episode,channel_base ");
        sbuffer.append(" where live_episode.is_delete = 0" +
                " and channel_base.is_enable = 1" +
                " and live_episode.is_sync = 1" +
                " and live_episode.father_id = channel_base.id");
        if (params.containsKey("startDate")) {
            sbuffer.append(" and live_episode.start_play_time >= '" + params.get("startDate") + "'");

        }
        if (params.containsKey("endDate")) {
            sbuffer.append(" and live_episode.start_play_time <= '" + params.get("endDate") + "' ");
        }
        if (params.containsKey("qipuId")) {
            sbuffer.append(" and live_episode.qipu_id = " + params.get("qipuId") + " ");
        }
        if (params.containsKey("pname")) {
            sbuffer.append(" and live_episode.program_name like '%" + StringEscapeUtils.escapeSql(params.get("pname")) + "%' ");
        }
        if (params.containsKey("cname")) {

            sbuffer.append(" and channel_base.name like '%" + StringEscapeUtils.escapeSql(params.get("cname")) + "%' ");
        }
        sbuffer.append(") tempA ,");
        sbuffer.append("(select channel_base.name, platform_control.father_id," +
                "group_concat(platform_control.play_platform  ) platforms" +
                " from channel_base , platform_control " +
                "where channel_base.is_enable = 1" +
                " and platform_control.father_id = channel_base.id " +
                " and  platform_control.available_status = 1 ");
        if (params.containsKey("platforms")) {
            sbuffer.append(" and platform_control.play_platform in (" + params.get("platforms") + ")");
        }
        sbuffer.append(" group by platform_control.father_id ) tempB " +
                " where tempA.cid = tempB.father_id" +
                " order by tempA.startPlayTime desc ");
        List<Object[]> result = programDataDao.getSession().createSQLQuery(sbuffer.toString()).setMaxResults(100).list();

        List<ProgramAvailable> ret = new ArrayList<ProgramAvailable>();
        ProgramAvailable temple = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Object[] single : result) {
            temple = new ProgramAvailable();
            temple.setQipuId(Long.valueOf("" + single[0]));
            temple.setType((Integer) single[1]);
            temple.setThumbnail((String) single[2]);
            temple.setPname((String) single[3]);
            temple.setStartPlayTime(sdf.format(single[4]));
            temple.setEndPlayTime(sdf.format(single[5]));
            temple.setBossStatus((String) single[6]);
            temple.setCname((String) single[7]);
            temple.setCid(Long.valueOf("" + single[8]));
            temple.setPageUrl((String) single[9]);
            temple.setPlatforms((String) single[10]);
            ret.add(temple);
        }
        return JSON.toJSONString(ret);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public boolean checkExistBindEpisode(long fatherId, long tKey) {
        String hql = null;
        long executeUpdate = 0;
        if (fatherId <= 0) {
            hql = "select count(id) from ProgramDataBase where type = 7 and t_key = ? ";
            executeUpdate = (Long) programDataDao.createQuery(hql)
                    .setParameter(0, tKey).uniqueResult();
        } else {
            hql = "select count(id) from ProgramDataBase where fatherId != ? and type = 7 and t_key = ?";
            executeUpdate = (Long) programDataDao.createQuery(hql)
                    .setParameter(0, fatherId)
                    .setParameter(1, tKey).uniqueResult();
        }

        return executeUpdate > 0;
    }

    @Override
    @Transactional
    public synchronized List<TProgram> findNotSyncTProgram(long fatherId) {
        List<TProgram> resultList = null;
        List<Criterion> cList = new ArrayList<Criterion>();
        if (fatherId > 0) {
            cList.add(Restrictions.eq("fatherId", (int) fatherId));
        }
        cList.add(Restrictions.ne("sync", 1));
        cList.add(Restrictions.gt("qipuId", 0L));
        cList.add(Restrictions.ge("startPlayTime", new Timestamp(System.currentTimeMillis() - DateTimeUtil.DAY_TIME * 10)));
        Criteria criteria = programDataDao.createCriteria();
        for (Criterion temp : cList) {
            criteria.add(temp);
        }
        criteria.setMaxResults(1000);
        List<ProgramData> dataList = programDataDao.find(criteria);
        if (dataList.size() > 0) {
//            int repeatedTimes = dataList.size() % 50 == 0 ? 0 : 1;
//            repeatedTimes += dataList.size() / 50;
            List<Long> updateList = new ArrayList<Long>();
            for (ProgramData temp : dataList) {
                if (temp.getSync() == 2) {
                    updateList.add(temp.getId());
//                    if( updateList.size() == 50){
//
//                    }
                }
            }
            String ids = updateList.toString();
            String hql = "update ProgramData set sync = 0 where sync = 2 and id in (" + ids.substring(1, ids.length() - 1) + ")";
            int executeUpdate = programDataDao.createQuery(hql).executeUpdate();
            logger.debug("[findNotSyncTProgram] executeUpdate:" + executeUpdate + " idLength:" + updateList.size());
        }
        resultList = transToTProgramList(dataList);
        return resultList;
    }

    @Override
    public void syncComplete(List<Long> idList) {
        if (idList.size() == 0) {
            return;
        }
        String ids = idList.toString();
        String hql = "update ProgramData set sync = 1 where sync = 2 and id in (" + ids.substring(1, ids.length() - 1) + ")";
        int executeUpdate = programDataDao.createQuery(hql).executeUpdate();
        logger.debug("[syncComplete] executeUpdate:" + executeUpdate + " idLength:" + idList.size());
    }

    @Override
    public void updateRecyclablePrograms() {
        String hql = "UPDATE live_episode as l INNER JOIN channel_base as c ON c.id = l.father_id " +
                "SET l.is_delete = 1, l.is_sync = 0 " +
                "WHERE l.is_delete = 0 AND l.father_id > 0 " +
                "AND ((l.start_play_time < CURDATE() AND c.live_type = 3) " +
                "OR (l.start_play_time < ADDDATE(NOW(), -5) AND c.live_type = 1)) " +
                "AND l.qipu_id > 0";
        int executeUpdate = programDataDao.getSession().createSQLQuery(hql).executeUpdate();
        logger.debug("[updateRecyclablePrograms] executeUpdate:" + executeUpdate);

    }

    private List<TProgram> transToTProgramList(List<ProgramData> dataList) {
        return transToTProgramList(dataList, false, true);
    }

    private List<TProgram> transToTProgramLibrary(List<ProgramData> dataList) {
        List<TProgram> resultList = new ArrayList<TProgram>();
        TProgram _TProgram = null;
        for (ProgramData tempData : dataList) {
            _TProgram = new TProgram();
            _TProgram.setId(tempData.getId());
            _TProgram.setFatherId(tempData.getFatherId());
            _TProgram.setQipuId(tempData.getQipuId());
            _TProgram.setPname(tempData.getPname());
            _TProgram.setPageUrl(tempData.getPageUrl());
            _TProgram.setPlayStatus(tempData.getPlayStatus());
            _TProgram.setBossStatus(tempData.getBossStatus());
            _TProgram.setType(tempData.getType());
            _TProgram.setEpisodeGrade(tempData.getEpisodeGrade());
            _TProgram.setOnlineStatus(tempData.getDeleteFlag() == 0);
            _TProgram.setRecommendRate(tempData.getRecommendRate());
            _TProgram.setHot(tempData.getHot());
            _TProgram.setTest(tempData.getTest());
            _TProgram.setStartPlayTime(DateTimeUtil.transLongFormat(tempData.getStartPlayTime().getTime()));
            _TProgram.setEndPlayTime(DateTimeUtil.transLongFormat(tempData.getStopPlayTime().getTime()));
            _TProgram.setUpdateTime(DateTimeUtil.transLongFormat(tempData.getUpdateTime().getTime()));
            _TProgram.setChannelName(tempData.getChannelName());
            _TProgram.setFormal(tempData.getFormal());
            _TProgram.setChannelHasStream(tempData.getChannelHasStream());
            _TProgram.setChannelLiveType(tempData.getChannelLiveType());
            _TProgram.setDirectorEnable(tempData.getDirectorEnable());

            if (tempData.getOaDocNo() != null) {
                _TProgram.setOaDocNo(tempData.getOaDocNo());
            }
            if (tempData.getOaDocUrl() != null) {
                _TProgram.setOaDocUrl(tempData.getOaDocUrl());
            }
            if (tempData.getOaDocEditorStatus() != null) {
                _TProgram.setOaDocEditorStatus(tempData.getOaDocEditorStatus());
            }
            resultList.add(_TProgram);
        }
        return resultList;
    }

    private List<TProgram> transToTProgramList(List<ProgramData> dataList, boolean needPic, boolean needDataBase) {
        List<TProgram> resultList = new ArrayList<TProgram>();
        TProgram tProgram = null;
        List<Long> idList = new ArrayList<Long>();
        Map<Long, TProgram> map = new HashMap<Long, TProgram>();
        boolean specialSingleDeal = needPic && dataList.size() == 1;
        for (ProgramData tempData : dataList) {
            tProgram = transToTProgram(tempData, specialSingleDeal);
            idList.add(tempData.getId());
            map.put(tempData.getId(), tProgram);
            resultList.add(tProgram);
        }
        if (needDataBase) {
            if (idList.size() > 0) {
                List<ProgramDataBase> programDataBaseList = findProgramDataBaseByFatherId(idList);
                TProgramBase _TProgramBase = null;
                for (ProgramDataBase tempBase : programDataBaseList) {
                    _TProgramBase = new TProgramBase();
                    _TProgramBase.setId(tempBase.getId());
                    _TProgramBase.setType(tempBase.getType());
                    _TProgramBase.setKey(tempBase.getKey());
                    _TProgramBase.setValue(tempBase.getValue());
                    map.get(tempBase.getFatherId()).addToRelationList(_TProgramBase);
                }
            }
        }
        return resultList;
    }

    private TProgram transToTProgram(ProgramData tempData, boolean needPic) {
        TProgram _TProgram = new TProgram();
        _TProgram.setId(tempData.getId());
        _TProgram.setFatherId(tempData.getFatherId());
        _TProgram.setPname(tempData.getPname());
        _TProgram.setType(tempData.getType());
        _TProgram.setStartPlayTime(DateTimeUtil.transLongFormat(tempData.getStartPlayTime().getTime()));
        _TProgram.setEndPlayTime(DateTimeUtil.transLongFormat(tempData.getStopPlayTime().getTime()));
        _TProgram.setUpdateTime(DateTimeUtil.transLongFormat(tempData.getUpdateTime().getTime()));
        if (tempData.getAddTime() != null) {
            _TProgram.setAddTime(DateTimeUtil.transLongFormat(tempData.getAddTime().getTime()));
        }
        _TProgram.setLastSortTime(tempData.getLastSortTime());
        _TProgram.setChatFake(tempData.getChatFake());
        _TProgram.setAdvertDuration(tempData.getAdvertDuration());
        _TProgram.setAdvertEnable(tempData.getAdvertEnable());
        _TProgram.setDirectorEnable(tempData.getDirectorEnable());
        _TProgram.setVipType(tempData.getVipType());
        if (tempData.getMatchSummary() != null) {
            _TProgram.setMatchSummary(tempData.getMatchSummary());
        }
        if (tempData.getStreamStartTime() == null) {
            _TProgram.setStreamStartPlayTime(_TProgram.getStartPlayTime());
        } else {
            _TProgram.setStreamStartPlayTime(DateTimeUtil.transLongFormat(tempData.getStreamStartTime().getTime()));
        }
        if (tempData.getStreamEndTime() == null) {
            _TProgram.setStreamEndPlayTime(_TProgram.getEndPlayTime());
        } else {
            _TProgram.setStreamEndPlayTime(DateTimeUtil.transLongFormat(tempData.getStreamEndTime().getTime()));
        }

        if (tempData.getNoticeStartTime() != null) {
            _TProgram.setNoticeStartTime(DateTimeUtil.transLongFormat(tempData.getNoticeStartTime().getTime()));
        }
        if (tempData.getNoticeStopTime() != null) {
            _TProgram.setNoticeStopTime(DateTimeUtil.transLongFormat(tempData.getNoticeStopTime().getTime()));
        }
        if (tempData.getProjectType() != null) {
            _TProgram.setProjectType(tempData.getProjectType());
        }

        if (tempData.getBarCode() != null) {
            _TProgram.setBarCode(tempData.getBarCode());
            String puyuData = queryPuYu(tempData.getBarCode(), null);
            if (puyuData != null) {
                _TProgram.setPuyuData(puyuData);
            }
        }
        if (tempData.getSnapPicUrl() != null) {
            _TProgram.setSnapPicUrl(tempData.getSnapPicUrl());
        }
        if (null != tempData.getProgramTag()) {
            _TProgram.setProgramTag(tempData.getProgramTag());
        }

        _TProgram.setNeedOA(tempData.getNeedOA());
        if (null != tempData.getOaDocNo()) {
            _TProgram.setOaDocNo(tempData.getOaDocNo());
        }
        if (null != tempData.getOaDocUrl()) {
            _TProgram.setOaDocUrl(tempData.getOaDocUrl());
        }
        if (null != tempData.getOaDocEditorStatus()) {
            _TProgram.setOaDocEditorStatus(tempData.getOaDocEditorStatus());
        }

        if (tempData.getId() > 0) {
            _TProgram.setResourceId(tempData.getResourceId());
            _TProgram.setSnapShotType(tempData.getSnapShotType());
            _TProgram.setSnapShotGap(tempData.getSnapShotGap());
            _TProgram.setWeiboTopic(tempData.getWeiboTopic());
            _TProgram.setLeftChannel(tempData.getLeftAudioChannel());
            _TProgram.setRightChannel(tempData.getRightAudioChannel());
            _TProgram.setDescription(tempData.getDescription());
            _TProgram.setAllowPopups(tempData.getAllowPopups() == 1);
            _TProgram.setAllowComment(tempData.getAllowComment() == 1);
            _TProgram.setTag(tempData.getTag());
            _TProgram.setAudioChannel(tempData.getAudioChannel());
            _TProgram.setImgSummaryId(tempData.getImageSummaryId());
            _TProgram.setMemberFree(tempData.getMemberFree() == 1);
            _TProgram.setMemberOnly(tempData.getMemberOnly() == 1);
            _TProgram.setBossStatus(tempData.getBossStatus());
            _TProgram.setFreeStatus(tempData.getFreeStatus() == 1);
            _TProgram.setVideoPieceLength(tempData.getVideoLength());
            _TProgram.setWaterMarkFlag(tempData.getWaterMarkFlag() == 1);
            _TProgram.setLogoHidden(tempData.getLogoHidden());
            _TProgram.setQipuId(tempData.getQipuId());
            _TProgram.setQitanId(tempData.getQitanId());
            _TProgram.setOnlineStatus(tempData.getDeleteFlag() == 0);
            _TProgram.setSynced(tempData.getSync() == 1);
            _TProgram.setOrderBy(tempData.getOrderBy());
            _TProgram.setPublicLevel(tempData.getPublicLevel());
            if (null != tempData.getAlbumName()) {
                _TProgram.setAlbumName(tempData.getAlbumName());
            }
            if (null != tempData.getReferContentType()) {
                _TProgram.setReferContentType(tempData.getReferContentType());
            }
            if (tempData.getLive() != null) {
                _TProgram.setLive(tempData.getLive().intValue());
            }
            _TProgram.setCarouselEpisode(tempData.getCarouselEpisode() == null ? 0 : tempData.getCarouselEpisode());
            _TProgram.setDuration(tempData.getDuration());
            if (needPic) {
                String img = ProductImgUtil.getProgramImg(tempData.getId());
                if (img != null) {
                    _TProgram.setLogoUrl(img);
                }
            }

            if (tempData.getPaidStartTime() != null) {
                _TProgram.setPaidStartTime(DateTimeUtil.transLongFormat(tempData.getPaidStartTime().getTime()));
            }
            if (tempData.getPaidEndTime() != null) {
                _TProgram.setPaidEndTime(DateTimeUtil.transLongFormat(tempData.getPaidEndTime().getTime()));
            }
            if (tempData.getDefaultLogoUrl() != null) {
                _TProgram.setDefaultLogoUrl(tempData.getDefaultLogoUrl());
            }
            if (tempData.getPageUrl() != null) {
                _TProgram.setPageUrl(tempData.getPageUrl());
            }
            _TProgram.setQiyiExclusive(tempData.getQiyiExclusive() == 1);
            _TProgram.setQiyiProduct(tempData.getQiyiProduct() == 1);
            _TProgram.setChannelName(tempData.getChannelName());
            _TProgram.setChannelLiveType(tempData.getChannelLiveType());
            _TProgram.setLockStatus(tempData.getIsLocked());
            _TProgram.setEpisodeGrade(tempData.getEpisodeGrade());
            _TProgram.setSubscribe(tempData.getSubscribe());
            _TProgram.setChatRoomId(tempData.getChatRoomId());
            _TProgram.setCategory(tempData.getCategory());
            _TProgram.setChatEnable(tempData.getChatEnable());
            _TProgram.setChatDisplay(tempData.getChatDisplay());
            _TProgram.setChatRights(tempData.getChatRights());
            _TProgram.setDaojuEnable(tempData.getDaojuEnable());
            _TProgram.setDaojuId(tempData.getDaojuId());
            _TProgram.setDaojuName(tempData.getDaojuName());
            _TProgram.setDaojuStar(tempData.getDaojuStar());
            _TProgram.setFormal(tempData.getFormal());

            /* 2016/05/20 new add start*/
            if (tempData.getSubjectUrl() != null) {
                _TProgram.setSubjectUrl(tempData.getSubjectUrl());
            }

            if (tempData.getRecommendRemark() != null) {
                _TProgram.setRecommendRemark(tempData.getRecommendRemark());
            }
            _TProgram.setMaxPlaybackPeriod(tempData.getMaxPlaybackPeriod());
            _TProgram.setRecommendRate(tempData.getRecommendRate());
            _TProgram.setPlayStatus(tempData.getPlayStatus());
            _TProgram.setChannelHasStream(tempData.getChannelHasStream());
            _TProgram.setHot(tempData.getHot());
            _TProgram.setTest(tempData.getTest());
            _TProgram.setCheckType(tempData.getCheckType());
            _TProgram.setChargeStatus(tempData.getChargeStatus());
            _TProgram.setBossInfo(tempData.getBossInfo());
            /* 2016/05/20 new add end */
            _TProgram.setChatPopups(tempData.getChatPopups());
            _TProgram.setTabControls(tempData.getTabConrtols());
            /*2018.01.12 add displayRecommend*/
            _TProgram.setDisplayRecommend(tempData.getDisplayRecommend());
            //20180403 add dbtRegion
            _TProgram.setDbtRegion(tempData.getDbtRegion());
            //20180410 add directorOpen
            _TProgram.setDirectorOpen(tempData.getDirectorOpen());


        }
        return _TProgram;

    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramData> getCurrentAndNextProgram(Long fatherId, Integer maxSize) {
        List<ProgramData> list = new ArrayList<>();
        String currentDay = DateTimeUtil.getCurrentDay();
        String nextDay = DateTimeUtil.getNextDay();
        List<ProgramData> programList = getBetweenDays(currentDay, nextDay, fatherId.intValue(), true);
        boolean hasPlaying = false;
        long countPlayTime = 0;
        long minPlayTotalTime = 900000;
        long minDuration = 60000;
        for (int i = 0; i < programList.size(); i++) {

            ProgramData single = programList.get(i);
            Timestamp start = single.getStartPlayTime();
            Timestamp end = single.getStopPlayTime();
            Timestamp now = new Timestamp(System.currentTimeMillis());
            // 节目时长小于60s,跳过
            if (end.getTime() - start.getTime() < minDuration) {
                continue;
            }

            long tempStartPlayTime;
            long tempEndPlayTime;

            if (now.compareTo(start) >= 0 && now.compareTo(end) < 0) {   //播放中
                ProgramData tempProgramData = programList.get(i);
                // 如果当前节目与上一个节目存在时间交错，设置当前节目的结束时间为下一个节目的开始时间
                if (i < programList.size() - 1) {
                    tempProgramData.setStopPlayTime(cutPrevProgram(
                            tempProgramData.getStopPlayTime(), programList.get(i + 1).getStartPlayTime()));
                }
                tempStartPlayTime = tempProgramData.getStartPlayTime().getTime();
                tempEndPlayTime = tempProgramData.getStopPlayTime().getTime();
                if (tempStartPlayTime != tempEndPlayTime && tempEndPlayTime - tempStartPlayTime >= minDuration) {
                    list.add(tempProgramData);
                    countPlayTime += tempEndPlayTime - tempStartPlayTime;
                }
                hasPlaying = true;

            } else if (now.compareTo(start) < 0) {   //还未播
                ProgramData tempProgramData = programList.get(i);
                // 如果当前节目与上一个节目存在时间交错，设置当前节目的结束时间为下一个节目的开始时间
                if (i < programList.size() - 1) {
                    tempProgramData.setStopPlayTime(cutPrevProgram(
                            tempProgramData.getStopPlayTime(), programList.get(i + 1).getStartPlayTime()));
                }
                tempStartPlayTime = tempProgramData.getStartPlayTime().getTime();
                tempEndPlayTime = tempProgramData.getStopPlayTime().getTime();
                if (tempStartPlayTime != tempEndPlayTime && tempEndPlayTime - tempStartPlayTime >= minDuration) {
                    list.add(tempProgramData);
                    countPlayTime += tempEndPlayTime - tempStartPlayTime;
                }
            }
            if (list.size() >= maxSize || (list.size() >= 3 && countPlayTime >= minPlayTotalTime)) {
                break;
            }
        }
        for (ProgramData single : list) {
            logger.info("Program startTime:{}", single.getStartPlayTime());
        }
        //当前有节目返回3个，当前无节目返回2个
        if (!hasPlaying && list.size() > maxSize - 1) {
            return list.subList(0, maxSize - 1);
        }
        return list;
    }

    @Override
    @Transactional
    public boolean updateProgramTimeList(List<TProgramTime> dataList) {
        boolean ret = true;
        for (TProgramTime data : dataList) {
            ProgramData programData = programDataDao.get(data.getId());
            if (null != programData) {
                programData.setStartPlayTime(new Timestamp(Long.parseLong(data.getStartPlayTime())));
                programData.setStopPlayTime(new Timestamp(Long.parseLong(data.getStopPlayTime())));
                programData.setStreamStartTime(new Timestamp(Long.parseLong(data.getStartStreamTime())));
                programData.setStreamEndTime(new Timestamp(Long.parseLong(data.getStopStreamTime())));
                ProgramData.calPlayStatus(programData);
                programData.setSync(0);
                programDataDao.saveOnly(programData);
            } else {
                ret = false;
            }
        }
        return ret;
    }

    @Override
    @Transactional
    public boolean updateProgramTimeList(Map<Long, TProgramTime> dataMap) {
        boolean flag = false;
        List<ProgramLog> programLogs = new ArrayList<ProgramLog>();
        try {
            Criteria criteria = programDataDao.createCriteria();
            criteria.add(Restrictions.in("id", dataMap.keySet()));
            List<ProgramData> programDataList = programDataDao.find(criteria);
            TProgramTime tempData = null;
            for (ProgramData temp : programDataList) {
                tempData = dataMap.get(temp.getId());

                ProgramLog programLog = new ProgramLog();
                programLog.setType(Constants.LogType.CAROUSEL_EPISODE_SORT.getIndex());
                programLog.setProgramId(tempData.getId());
                programLog.setUser(Constants.SYSTEM_USER_SIGN);
                programLog.setDescription(String.format(FORMAT_SORT_LOG, temp.getStartPlayTime().getTime(), temp.getStopPlayTime().getTime(), tempData.getStartPlayTime(), tempData.getStopPlayTime()));
                programLogs.add(programLog);

                temp.setStartPlayTime(new Timestamp(Long.parseLong(tempData.getStartPlayTime())));
                temp.setStopPlayTime(new Timestamp(Long.parseLong(tempData.getStopPlayTime())));
                temp.setStreamStartTime(new Timestamp(Long.parseLong(tempData.getStartStreamTime())));
                temp.setStreamEndTime(new Timestamp(Long.parseLong(tempData.getStopStreamTime())));
                ProgramData.calPlayStatus(temp);
                temp.setSync(0);
            }
            flag = batchUpdateProgramList(programDataList);
        } catch (Exception e) {
            logger.error("Exception ", e);
            flag = false;
        }
        if (flag) {
            programAsyncService.saveProgramLogList(programLogs);
        }
        logger.info("[updateProgramTimeList] flag =" + flag);
        return flag;
    }

    @Override
    public boolean batchUpdateProgramList(List<ProgramData> programDataList) {
        boolean modifyFlag = false;
        Session session = programDataDao.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();
        try {
            for (ProgramData temp : programDataList) {
                session.update(temp);
            }
            transaction.commit();
            modifyFlag = true;
        } catch (Exception e) {
            logger.error(e.getMessage());
            transaction.rollback();
        } finally {
            session.close();
        }
        return modifyFlag;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramData> findProgramDataList(TFilter filter, String orderBy, String order) {
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        Order realOrder = null;
        String[] orderByArr = orderBy.split(",");
        String[] orderArr = order.split(",");
        List<Order> realOrderList = new ArrayList<Order>();
        int length = orderByArr.length;
        for (int i = 0; i < length; i++) {
            if ("asc".equalsIgnoreCase(orderArr[i])) {
                realOrder = Order.asc(orderByArr[i]);
            } else if ("desc".equalsIgnoreCase(orderArr[i])) {
                realOrder = Order.desc(orderByArr[i]);
            }
            if (realOrder != null) {
                realOrderList.add(realOrder);
            }
        }

        List<ProgramData> dataList = programDataDao.find(filterList, realOrderList.toArray(new Order[]{}));
        return dataList;
    }

    @Override
    public String queryPuYu(String barCode, String cprVideoName) {
        if (!StringUtils.isBlank(barCode)) {
            return ApiPuYuRequestUtil.queryForPuyuBarCode(barCode);
        } else if (!StringUtils.isBlank(cprVideoName)) {
            return ApiPuYuRequestUtil.queryForPuyuCprVideoName(cprVideoName);
        }
        return null;
    }

    @Override
    public List<ProgramData> checkListQuery(long minStartTime, long maxStartTime, boolean findDelete) {
        StringBuffer sbuffer = new StringBuffer("select program from ProgramData program,ChannelBase channel where program.fatherId = channel.id ");
        sbuffer.append(" and channel.isEnable != -1 ");
        sbuffer.append(" and channel.liveType = 2 ");
        sbuffer.append(" and channel.formal = 1 ");
        if (!findDelete) {
            sbuffer.append(" and program.deleteFlag = 0 ");
        }
        //
        sbuffer.append(" and program.startPlayTime >= '" + DateTimeUtil.transLongFormat(minStartTime) + "'");
        sbuffer.append(" and program.startPlayTime <= '" + DateTimeUtil.transLongFormat(maxStartTime) + "'");
        sbuffer.append(" order by program.startPlayTime asc ");
        Query query = programDataDao.createQuery(sbuffer.toString());
        List<ProgramData> programDataList = query.list();
        return programDataList;
    }

    @Override
    public List<ProgramData> doQueryNoticeStart(long minNoticeStartTime, long maxNoticeStartTime) {
        StringBuffer sbuffer = new StringBuffer("select program from ProgramData program,ChannelBase channel where program.fatherId = channel.id ");
        sbuffer.append(" and channel.isEnable != -1 ");
        sbuffer.append(" and channel.liveType = 2 ");
        sbuffer.append(" and channel.formal = 1 ");
        sbuffer.append(" and program.deleteFlag = 0 ");
        sbuffer.append(" and program.noticeStartTime is not null ");
        sbuffer.append(" and program.noticeStartTime >= '" + DateTimeUtil.transLongFormat(minNoticeStartTime) + "'");
        sbuffer.append(" and program.noticeStartTime <= '" + DateTimeUtil.transLongFormat(maxNoticeStartTime) + "'");
        sbuffer.append(" order by program.noticeStartTime asc ");
        Query query = programDataDao.createQuery(sbuffer.toString());
        List<ProgramData> programDataList = query.list();
        return programDataList;
    }

    @Override
    public List<ProgramData> findSubscribeQuery(long minStartTime, long maxStartTime) {
        StringBuffer sbuffer = new StringBuffer("select program from ProgramData program,ChannelBase channel where program.fatherId = channel.id ");
        sbuffer.append(" and channel.isEnable != -1 ");
        sbuffer.append(" and channel.liveType = 2 ");
        sbuffer.append(" and channel.formal = 1 ");
        sbuffer.append(" and program.deleteFlag = 0 ");
        sbuffer.append(" and program.subscribe = 0 ");
        sbuffer.append(" and program.noticeStartTime >= '" + DateTimeUtil.transLongFormat(minStartTime) + "'");
        sbuffer.append(" and program.noticeStartTime <= '" + DateTimeUtil.transLongFormat(maxStartTime) + "'");
        sbuffer.append(" order by program.noticeStartTime asc ");
        Query query = programDataDao.createQuery(sbuffer.toString());
        List<ProgramData> programDataList = query.list();
        return programDataList;
    }

    public List<ProgramData> programEndQuery(long minEndTime, long maxEndTime) {
        StringBuffer sbuffer = new StringBuffer("select program from ProgramData program,ChannelBase channel ,ChannelTag cnlTag ");
        sbuffer.append(" where program.fatherId = channel.id ");
        sbuffer.append(" and channel.isEnable != -1 ");
        sbuffer.append(" and channel.liveType = 2 ");
        sbuffer.append(" and program.deleteFlag = 0 ");
        sbuffer.append(" and program.stopPlayTime >= '" + DateTimeUtil.transLongFormat(minEndTime) + "'");
        sbuffer.append(" and program.stopPlayTime < '" + DateTimeUtil.transLongFormat(maxEndTime) + "'");
        sbuffer.append(" and cnlTag.fatherId = channel.id ");
        sbuffer.append(" and (cnlTag.tag2 != 200978719 or cnlTag.tag1 != 200003919)");
        sbuffer.append(" order by program.startPlayTime asc ");
        Query query = programDataDao.createQuery(sbuffer.toString());
        List<ProgramData> programDataList = query.list();
        return programDataList;
    }

    @Override
    public List<ProgramCheckData> findForceCheck() {

        String sql = "select program.id programId,program.father_id channelId from live_episode program where force_check = 1";
        Query query = programDataDao.getSession().createSQLQuery(sql).addScalar("programId", new LongType()).addScalar("channelId", new LongType());
        List<Object[]> result = query.list();
        List<ProgramCheckData> list = new ArrayList<ProgramCheckData>();
        logger.info("[findForceCheck][ready do check ]" + result.size());
        if (result.size() == 0) {
            return list;
        }
        ProgramCheckData temp = null;
        for (Object[] single : result) {
            temp = new ProgramCheckData();
            temp.setId((Long) single[0]);
            temp.setFatherId((Long) single[1]);
            list.add(temp);
        }
        return list;
    }

    @Override
    public boolean addStreamError(int errorCode, long channelId, long programId, List<String> streamTypeList) {
        try {
            ProgramData programData = findProgramDataById(programId);
            Gson gson = new Gson();
            List<StreamErrorData> errorList = null;

            String streamError = programData.getStreamError();
            if (null == streamError || StringUtils.isBlank(streamError)) {
                errorList = new ArrayList<>();
            } else {
                errorList = gson.fromJson(streamError, new TypeToken<List<StreamErrorData>>() {
                }.getType());
            }

            for (String streamType : streamTypeList) {
                StreamErrorData streamErrorData = new StreamErrorData();
                streamErrorData.setCode(errorCode);
                streamErrorData.setTime(DateTimeUtil.transLongFormat(System.currentTimeMillis()));
                streamErrorData.setStreamType(streamType);

                errorList.add(streamErrorData);
            }

            programData.setStreamError(gson.toJson(errorList));
            logger.info("[ProgramServiceImpl][addStreamError][streamError={}]", programData.getStreamError());

            saveProgramData(programData);
        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][addStreamError][exception={}]", e);
            return false;
        }

        return true;
    }

    @Override
    public List<ProgramDataExpired> getExpiredProgramList() {
        Criteria filters = programDataExpiredDao.createCriteria();
        filters.add(Restrictions.eq("isDeleted", 0));
        return programDataExpiredDao.find(filters);
    }

    @Override
    public void insertExpiredProgramList(List<ProgramDataExpired> list) {

        for (ProgramDataExpired program : list) {
            try {
                programDataExpiredDao.saveOnly(program);
            } catch (Exception e) {
                logger.info("[ProgramServiceImpl][insertExpiredProgramList][Exception={}]", e);
            }
        }
    }

    @Override
    public void updateDeletedExpiredProgram(ProgramDataExpired program) {
        program.setIsDeleted(1);
        programDataExpiredDao.merge(program);

    }

    @Override
    public boolean toggleLockProgram(long id, int lockType) {
        int effectNum = 0;
        String sql = "update live_episode set is_locked = " + lockType + " where live_episode.id = " + id;
        Query query = programDataDao.getSession().createSQLQuery(sql);
        effectNum = query.executeUpdate();
        logger.info("[ProgramServiceImpl][toggleLockProgram][effectNum={}]", effectNum);
        return true;
    }

    public void doEndForceCheck(long programId) {
        int effectNum = 0;
        String sql = "update live_episode set force_check = 0 where live_episode.id = " + programId;
        Query query = programDataDao.getSession().createSQLQuery(sql);
        effectNum = query.executeUpdate();
        logger.info("[doEndForceCheck][effectNum={}]", effectNum);
        //  return effectNum;
    }

    public long findYesDayEndTime(long channelId, long newStartTime) {
        long maxStartTime = DateTimeUtil.getDayEndTime(newStartTime - DateTimeUtil.DAY_TIME);
        long minStartTime = DateTimeUtil.getZeroTime(maxStartTime);
        List<Criterion> expressionList = new ArrayList<>();
        expressionList.add(Restrictions.eq("fatherId", (int) channelId));
        expressionList.add(Restrictions.eq("deleteFlag", 0));
        expressionList.add(Restrictions.eq("illegalStatus", 0));
        expressionList.add(Restrictions.between("startPlayTime", new Timestamp(minStartTime), new Timestamp(maxStartTime)));
        //  expressionList.add(Restrictions.ge("stopPlayTime", new Timestamp(minStartTime)));
        Criteria crit = programDataDao.createCriteria();
        for (Criterion criterion : expressionList) {
            crit.add(criterion);
        }
        //    crit.addOrder(Order.desc("stopPlayTime")).setMaxResults(1);
        crit.addOrder(Order.desc("stopPlayTime"));
        List<ProgramData> list = programDataDao.find(crit);
        if (list.size() < 1) {
            logger.info("[findYesDayEndTime] not find minstartTime");
            return newStartTime;
        } else {
            ProgramData programData = list.get(0);
            long yestodayEndTime = programData.getStopPlayTime().getTime();
            return yestodayEndTime < newStartTime ? newStartTime : yestodayEndTime;
        }
    }

    public long findLastEndTime(long channelId, long newStartTime) {
        List<Criterion> expressionList = new ArrayList<>();
        expressionList.add(Restrictions.eq("fatherId", (int) channelId));
        expressionList.add(Restrictions.eq("deleteFlag", 0));
        expressionList.add(Restrictions.eq("illegalStatus", 0));
        expressionList.add(Restrictions.ge("stopPlayTime", new Timestamp(newStartTime)));
        Criteria crit = programDataDao.createCriteria();
        for (Criterion criterion : expressionList) {
            crit.add(criterion);
        }
        crit.addOrder(Order.desc("stopPlayTime")).setMaxResults(1);
        List<ProgramData> list = programDataDao.find(crit);
        if (list.size() < 1) {
            logger.info("[findYesDayEndTime] not find minstartTime");
            return newStartTime;
        } else {
            ProgramData programData = list.get(0);
            return programData.getStopPlayTime().getTime();
        }
    }


    private Timestamp cutPrevProgram(Timestamp curStop, Timestamp nextStart) {

        if (curStop.compareTo(nextStart) >= 0) {
            return nextStart;
        }

        return curStop;
    }

    /*  */

    @Override
    public List<ProgramData> findNoBroadcastPrograms(long startTime, long endTime, int start, int max) {
        // public List<ProgramData> findNoBroadcastPrograms(long startTime,long endTime, int start, int max) {
        StringBuffer sql = new StringBuffer();
        sql.append(" SELECT {program.*} FROM live_episode program LEFT JOIN program_platform_control ppc ON program.id = ppc.program_id left join platform_control pc on program.father_id = pc.father_id ");
        sql.append(" where program.start_play_time >= ? and program.start_play_time < ? ");
        sql.append(" and program.qipu_id > 0 ");
        sql.append(" and program.is_delete = 0 ");
        sql.append(" and ppc.id is null and pc.id is not null");
        sql.append(" group by program.id ");
        sql.append(" order by program.start_play_time ");
        List<ProgramData> programDataList = programDataDao.getSession().createSQLQuery(sql.toString())
                .addEntity("program", ProgramData.class)
                .setTimestamp(0, new Timestamp(startTime))
                .setTimestamp(1, new Timestamp(endTime))
                .setFirstResult(start)
                .setMaxResults(max)
                .list();
        return programDataList;
    }

    @Override
    public List<TLivingInfo> getTLivingInfo() {
        StringBuilder sql = new StringBuilder();
        Map<String, TLivingInfo> map = new HashMap<String, TLivingInfo>();
        sql.append("  SELECT  channel_base.name, ");
        sql.append("  channel_base.qipu_id, ");
        sql.append("  channel_base.live_type,");
        sql.append("  live_episode.program_name,");
        sql.append("  live_episode.qipu_id, ");
        sql.append("  live_episode.boss_status,");
        sql.append("  live_episode.episode_grade,");
        sql.append("  live_episode.page_url,");
        sql.append("  live_episode.start_play_time, ");
        sql.append("  live_episode.stop_play_time, ");
        sql.append("  channel_base.id");
        sql.append("  FROM channel_base");
        sql.append("  JOIN live_episode ON channel_base.id = live_episode.father_id");
        sql.append("  WHERE channel_base.live_type = 2 ");
        sql.append("  AND channel_base.is_enable = 1");
        sql.append("  AND live_episode.start_play_time < ADDDATE(now(), 7) ");
        sql.append("  AND live_episode.stop_play_time > now() ");
        sql.append("  AND live_episode.`is_delete`=0");
        List result = programDataDao.getSession().createSQLQuery(sql.toString()).list();


        List<TLivingInfo> ret = new ArrayList<>();
        for (Object single : result) {
            Object[] obj = (Object[]) single;
            TLivingInfo temp = new TLivingInfo();
            temp.setChannelName((String) obj[0]);
            temp.setChannelQipuId(((BigInteger) obj[1]).longValue());
            temp.setLiveType((Integer) obj[2]);
            temp.setProgramName((String) obj[3]);
            temp.setProgramQipuId(((BigInteger) obj[4]).longValue());
            temp.setBossStatus((String) obj[5]);
            temp.setEpisodeGrade((Integer) obj[6]);
            temp.setPageUrl((String) obj[7]);
            temp.setStartPlayTime(obj[8].toString());
            temp.setStopPlayTime(obj[9].toString());
            map.put("" + obj[10], temp);
        }
        if (map.size() == 0) {
            return ret;
        } else {
            StringBuilder sql2 = new StringBuilder();
            String ids = map.keySet().toString();
            sql2.append("SELECT father_id,GROUP_CONCAT(IF(LENGTH(dolby_ch)=0,url,dolby_ch)) FROM live_stream WHERE father_id IN (");
            sql2.append(ids.substring(1, ids.length() - 1));
            sql2.append(") AND status != - 1 AND format_type IN ('TS', 'FLV' , 'DOLBY')  GROUP BY father_id");
            List result2 = programDataDao.getSession().createSQLQuery(sql2.toString()).list();
            TLivingInfo temp = null;
            for (Object single : result2) {
                Object[] obj = (Object[]) single;
                temp = map.get("" + obj[0]);
                temp.setStreamInfo(obj[1].toString());
            }
            ret.addAll(map.values());
            return ret;
        }
    }

    @Override
    public List<ProgramData> getCurrentProgram(int fatherId) {
        logger.info("[ProgramServiceImpl][getCurrentProgram][fatherId={}]", fatherId);
        List<Criterion> cList = new ArrayList<>();
        cList.add(Restrictions.le("startPlayTime", new Timestamp(System.currentTimeMillis())));
        cList.add(Restrictions.ge("stopPlayTime", new Timestamp(System.currentTimeMillis())));
        if (fatherId > 0) {
            cList.add(Restrictions.eq("fatherId", fatherId));
        } else {
            return null;
        }

        cList.add(Restrictions.eq("deleteFlag", 0));
        List<Order> orderList = new ArrayList<>();
        orderList.add(Order.asc("id"));
        return queryDataByCriterion(cList, orderList, -1);
    }

    @Override
    public String getMaxDurationProgram(long fatherId) {
        StringBuffer sql = new StringBuffer();
        sql.append("select id, program_name, TIMESTAMPDIFF(SECOND, start_play_time,stop_play_time) as dura from live_episode where stop_play_time >= NOW() and ");
        sql.append("father_id = " + fatherId + " and ");
        sql.append("is_delete != 1 order by dura desc");

        List result = programDataDao.getSession().createSQLQuery(sql.toString()).setMaxResults(1).list();

        if (null != result && result.size() > 0) {
            Object[] programInfo = (Object[]) result.get(0);
            // id: obj[0]     name: obj[12]    duration: obj[56]
            return "{'id':" + programInfo[0] + ",'name':'" + programInfo[1] + "','duration':" + programInfo[2] + "}";
        } else {
            return "";
        }
    }

    public int updateToForceCheck(long programId) {
        String sql = "update live_episode set force_check = 1 where id = " + programId;
        int executeUpdate = programDataDao.getSession().createSQLQuery(sql).executeUpdate();
        logger.info("[updateToForceCheck][pid={}][executeUpdate={}]", programId, executeUpdate);
        return executeUpdate;
    }

    @Override
    public int updateMaxPlaybackPeriod(long fatherId, int maxPlaybackPeriod) {
        logger.info("[ProgramServiceImpl][updateMaxPlaybackPeriod][fatherId={}][maxPlaybackPeriod={}]", fatherId, maxPlaybackPeriod);
        StringBuffer sql = new StringBuffer();
        sql.append("UPDATE live_episode SET max_playback_period = '" + maxPlaybackPeriod + "' , is_sync = 0 ");
        sql.append(" WHERE father_id = " + fatherId + " AND ");
        sql.append("is_delete != 1 AND start_play_time > concat(ADDDATE(CURDATE(), -4), ' 23:59:59')");
        try {
            int executeUpdate = programDataDao.getSession().createSQLQuery(sql.toString()).executeUpdate();
            logger.info("[ProgramServiceImpl][updateMaxPlaybackPeriod][fatherId={}][executeUpdate={}]", fatherId, executeUpdate);
            return executeUpdate;
        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][updateMaxPlaybackPeriod][fatherId={}][exception={}]", fatherId, e);
        }
        return -1;
    }

    @Override
    //   @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updatePlayStatus() {
        logger.info("[ProgramServiceImpl][updatePlayStatus] start");
        long current = System.currentTimeMillis();
        int updateCount = 0;
        List<ProgramData> programDataList = new ArrayList<>();
        List<ProgramData> toSendDataList = new ArrayList<>();
//        String currentNow = DateTimeUtil.transLongFormat(current);
//        String currentNowShort = DateTimeUtil.transShortFormat(current);

//        StringBuffer sql = new StringBuffer();
//        sql.append("UPDATE live_episode p JOIN channel_base c ON p.father_id = c.id ");
//        sql.append("SET p.play_status=(CASE WHEN '" + currentNow + "' < p.start_play_time THEN 0 ");
//        sql.append("WHEN '" + currentNow + "' < p.stop_play_time THEN 1 WHEN '" + currentNow + "' < TIMESTAMPADD(SECOND, c.max_playback_period, p.start_play_time) THEN 2 ELSE 3 END), p.is_sync = 0 ");
//        sql.append("WHERE p.is_delete != 1 AND p.qipu_id != 0 AND p.play_status != (CASE WHEN '" + currentNow + "' < p.start_play_time THEN 0 ");
//        sql.append("WHEN '" + currentNow + "' < p.stop_play_time THEN 1 WHEN '" + currentNow + "' < TIMESTAMPADD(SECOND, c.max_playback_period, p.start_play_time) THEN 2 ELSE 3 END) ");
//        sql.append("AND p.start_play_time > CONCAT(ADDDATE('" + currentNowShort + "', -3), ' 00:00:00') AND p.start_play_time < CONCAT(ADDDATE('" + currentNowShort + "', 5), ' 23:59:59')");

        // 更新直播中的节目播放状态
        StringBuffer liveSql = new StringBuffer();
        liveSql.append("SELECT {p.*} FROM live_episode p ");
        liveSql.append("WHERE p.start_play_time < NOW() AND p.stop_play_time > NOW() ");
        liveSql.append("AND p.qipu_id > 0 AND p.play_status != 1 AND p.is_delete != 1 ");

        // 更新回看中的节目播放状态
        StringBuffer replaySql = new StringBuffer();
        replaySql.append("SELECT {p.*} FROM live_episode p JOIN channel_base c ON p.father_id = c.id ");
        replaySql.append("WHERE p.stop_play_time < NOW() AND p.start_play_time > TIMESTAMPADD(SECOND, 0-c.max_playback_period, NOW()) ");
        replaySql.append("AND p.qipu_id > 0 AND p.play_status != 2 AND p.is_delete != 1 ");

        // 回看结束的节目播放状态
        StringBuffer requestSql = new StringBuffer();
        requestSql.append("SELECT {p.*} FROM live_episode p JOIN channel_base c ON p.father_id = c.id ");
        requestSql.append("WHERE p.stop_play_time < NOW() AND p.start_play_time > CONCAT(ADDDATE(CURDATE(), -4),' 00:00:00') "); // 4 表示最大回看时间（三天）加上一天
        requestSql.append("AND p.start_play_time < TIMESTAMPADD(SECOND, 0-c.max_playback_period, NOW()) ");
        requestSql.append("AND p.qipu_id > 0 AND p.play_status != 3 AND p.is_delete != 1 ");


        try {
            List<ProgramData> liveProgramDataList = programDataDao.getSession().createSQLQuery(liveSql.toString())
                    .addEntity("p", ProgramData.class)
                    .setMaxResults(300)
                    .list();

            for (ProgramData program : liveProgramDataList) {
                program.setPlayStatus(1);
                program.setSync(0);
                programDataList.add(program);
                if (program.getType() != 7) {
                    toSendDataList.add(program);
                }
            }

            List<ProgramData> replayProgramDataList = programDataDao.getSession().createSQLQuery(replaySql.toString())
                    .addEntity("p", ProgramData.class)
                    .setMaxResults(300)
                    .list();

            for (ProgramData program : replayProgramDataList) {
                program.setPlayStatus(2);
                program.setSync(0);
                programDataList.add(program);
                if (program.getType() != 7) {
                    toSendDataList.add(program);
                }
            }

            List<ProgramData> requestProgramDataList = programDataDao.getSession().createSQLQuery(requestSql.toString())
                    .addEntity("p", ProgramData.class)
                    .setMaxResults(300)
                    .list();

            for (ProgramData program : requestProgramDataList) {
                program.setPlayStatus(3);
                program.setSync(0);
                programDataList.add(program);
                if (program.getType() != 7) {
                    toSendDataList.add(program);
                }
            }
            batchUpdateProgramDataList(programDataList);
            logger.info("[ProgramServiceImpl][updatePlayStatus][count={}]", programDataList.size());
            if (toSendDataList.size() > 0) {
                logger.info("[ProgramServiceImpl] addVVNotify case playStatus update ");
                for (ProgramData programData : toSendDataList) {
                    programAsyncService.addVVNotify(programData);
                }
            }

            return programDataList.size();

        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][updatePlayStatus][Exception={}]", e);
        }
        return -1;
    }

    private void batchUpdateProgramDataList(List<ProgramData> programDataList) {
        for (ProgramData program : programDataList) {
            programDataDao.save(program);
        }
    }

    @Override
    public int updatePanoformat(long fatherId, String panoFormat) {
        logger.info("[ProgramServiceImpl][updatePanoformat][fatherId={}][panoFormat={}]", fatherId, panoFormat);
        StringBuffer sql = new StringBuffer();
        sql.append("UPDATE live_episode SET pano_format = '" + panoFormat + "', is_sync = 0 ");
        sql.append(" WHERE father_id = " + fatherId + " AND ");
        sql.append("is_delete != 1 AND start_play_time > concat(ADDDATE(CURDATE(), -4), ' 23:59:59')");
        try {
            int executeUpdate = programDataDao.getSession().createSQLQuery(sql.toString()).executeUpdate();
            logger.info("[ProgramServiceImpl][updatePanoformat][fatherId={}][executeUpdate={}]", fatherId, executeUpdate);
            return executeUpdate;
        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][updatePanoformat][fatherId={}][exception={}]", fatherId, e);
        }
        return -1;
    }

    @Override
    public int updateThreeD(long fatherId, String threeDFormat) {
        logger.info("[ProgramServiceImpl][updateThreeD][fatherId={}][Format={}]", fatherId, threeDFormat);
        StringBuffer sql = new StringBuffer();
        sql.append("UPDATE live_episode SET three_d_format = '" + threeDFormat + "', is_sync = 0 ");
        sql.append(" WHERE father_id = " + fatherId + " AND ");
        sql.append("is_delete != 1 AND start_play_time > concat(ADDDATE(CURDATE(), -4), ' 23:59:59')");
        try {
            int executeUpdate = programDataDao.getSession().createSQLQuery(sql.toString()).executeUpdate();
            logger.info("[ProgramServiceImpl][updateThreeD][fatherId={}][executeUpdate={}]", fatherId, executeUpdate);
            return executeUpdate;
        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][updateThreeD][fatherId={}][exception={}]", fatherId, e);
        }
        return -1;
    }

    public void notifyProgramInLive(long channelId, boolean channgeToRun, String streamName) {
        logger.info("[notifyProgramInLive][channelId={}][channgeToRun={}][streamName={}]", channelId, channgeToRun, streamName);
        String checkDateTime = DateTimeUtil.transLongFormat(System.currentTimeMillis());
        String skipTest = getSkipTestFlag() ? "" : " and program.test != 1 and channel.formal = 1 ";
        String sql = "select {program.*}, {channel.*}  from live_episode program, channel_base channel where program.father_id = channel.id" +
                " and channel.live_type = 2 and program.is_delete = 0 and channel.is_enable = 1 " + skipTest +
                " and program.start_play_time <= '" + checkDateTime + "' and program.stop_play_time >= '" + checkDateTime + "'" +
                " and channel.id = " + channelId;
        List result = programDataDao.getSession().createSQLQuery(sql).
                addEntity("program", ProgramData.class).addEntity("channel", ChannelBase.class).list();
        MailContentUtil.ContentType contentType = channgeToRun ? MailContentUtil.ContentType.STREAM_START_REMIND : MailContentUtil.ContentType.STREAM_STOP_REMIND;
        logger.info("[notifyProgramInLive] query list length = {}", result.size());
        String eventTime = DateTimeUtil.transLongFormat(System.currentTimeMillis());
        for (Object single : result) {
            Object[] obj = (Object[]) single;
            ProgramData programData = (ProgramData) obj[0];
            ChannelBase channelBase = (ChannelBase) obj[1];
            Map<String, String> map = new HashMap<String, String>();
            map.put(MailConstant.C_ID, "" + channelBase.getId());
            map.put(MailConstant.C_NAME, channelBase.getName());
            map.put(MailConstant.C_QIPU_ID, "" + channelBase.getQipuId());
            map.put(MailConstant.P_NAME, "" + programData.getPname());
            map.put(MailConstant.P_ID, "" + programData.getId());
            map.put(MailConstant.P_QIPU_ID, "" + programData.getQipuId());
            map.put(MailConstant.P_START_TIME, DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()));
            map.put(MailConstant.P_STOP_TIME, DateTimeUtil.transLongFormat(programData.getStopPlayTime().getTime()));
            map.put(MailConstant.STREAM_NAME, streamName);
            map.put("eventTime", eventTime);
            notifyMailService.addMailAsyncTask(MailConstant.TOS_TYPE_FROM_LOG + MailConstant.TOS_TYPE_P_MAIL_TYPE, contentType.getTypeIndex(), map);
            notifyMailService.addStreamMsgAsyncTask(channgeToRun, map);
        }
    }

    @Override
    public List<TProgram> getSyncQisuProgramList(int resultsBegin, int resultsLimit) {
        List<TProgram> results = new ArrayList<>();
        StringBuffer sql = new StringBuffer();

        sql.append("select qipu_id, boss_status from live_episode where is_delete = 0  and qipu_id > 0 ");
        sql.append("and (type != 7 or (type = 7 and start_play_time < ADDDATE(CURDATE(), 3)))");

        List<Object[]> sqlResult = programDataDao.getSession().createSQLQuery(sql.toString())
                .addScalar("qipu_id", new LongType())
                .addScalar("boss_status", new StringType())
                .setFirstResult(resultsBegin)
                .setMaxResults(resultsLimit)
                .list();

        for (Object[] simple : sqlResult) {
            TProgram programData = new TProgram();
            programData.setQipuId((Long) simple[0]);
            programData.setBossStatus((String) simple[1]);
            results.add(programData);
        }

        return results;

    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public TProgramLogPage getProgramLogList(TPage page, TFilter filter) {
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        Page<ProgramLog> dbPage = TransUtil.buildPage(page);
        Page<ProgramLog> pageData = programLogDao.findPage(dbPage, filterList);
        List<ProgramLog> dataList = pageData.getResult();
        TProgramLogPage carouselPage = new TProgramLogPage();
        page.setTotalCount(pageData.getTotalCount());
        carouselPage.setTPage(page);
        List<TProgramLog> tCarouselList = transToProgramLogList(dataList);
        carouselPage.setResult(tCarouselList);
        return carouselPage;
    }

    @Transactional
    public List<String> searchForLogUser(long channelId) {
        Criteria criteria = programLogDao.createCriteria();
        criteria.add(Restrictions.eq("programId", channelId));
        long maxTime = System.currentTimeMillis();
        long minTime = System.currentTimeMillis() - 90 * DateTimeUtil.DAY_TIME;
        criteria.add(Restrictions.between("addTime", new Timestamp(minTime), new Timestamp(maxTime)));
        criteria.add(Restrictions.not(Restrictions.in("user", SYSTEM_USRS)));
        criteria.setProjection(Projections.groupProperty("user"));
        return criteria.list();
    }

    @Override
    public void saveProgramLog(ProgramLog programLog) {
        programLogDao.saveOnly(programLog);
    }


    @Override
    public void saveProgramLogList(List<ProgramLog> programLogList) {
        for (ProgramLog programLog : programLogList) {
            programLogDao.saveOnly(programLog);
        }
    }

    private List<TProgramLog> transToProgramLogList(List<ProgramLog> dataList) {
        List<TProgramLog> resultList = new ArrayList<>();
        TProgramLog tChannelLog = null;
        for (ProgramLog tempData : dataList) {
            tChannelLog = transToProgramLog(tempData);
            resultList.add(tChannelLog);
        }
        return resultList;
    }

    private TProgramLog transToProgramLog(ProgramLog tempData) {
        TProgramLog _TProgramLog = new TProgramLog();
        _TProgramLog.setId(tempData.getId());
        _TProgramLog.setProgramId(tempData.getProgramId());
        _TProgramLog.setUser(tempData.getUser());
        _TProgramLog.setType(tempData.getType());
        _TProgramLog.setDescr(tempData.getDescription());
        _TProgramLog.setAddTime(DateTimeUtil.transLongFormat(tempData.getAddTime().getTime()));
        return _TProgramLog;
    }

    public String saveSnapshot(long taskId, String snapshot, String errcode, String errmsg) {
        SnapshotTask snapshotTask = new SnapshotTask();
        snapshotTask.setTaskId(taskId);
        snapshotTask.setErrMsg(errmsg);
        snapshotTask.setErrCode(errcode);
        snapshotTask.setSnapshot(snapshot);
        snapshotTask.setAddTime(new Timestamp(System.currentTimeMillis()));
        snapshotTaskDataDao.saveOnly(snapshotTask);
        return snapshotTask.getId() > 0 ? Constants.CODE_SUC : Constants.CODE_ERROR;
    }

    @Override

    public long getProgramCountByFatherId(long fatherId) {
        long result = 0;
        try {
            StringBuffer sql = new StringBuffer();
            sql.append("select count(*) as total from live_episode where ");
            sql.append("father_id = " + fatherId + " and ");
            sql.append("is_delete != 1");

            String total = programDataDao.getSession().createSQLQuery(sql.toString())
                    .addScalar("total", new StringType()).list().get(0).toString();

            result = Long.valueOf(total);
        } catch (Exception e) {
            logger.info("[ProgramServiceImpl][getProgramCountByFatherId][fatherId={}] exception = {}", fatherId, e);
        }

        return result;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramAdvert> findAdvertByfQipuId(long fatherQipuId) {
        return programAdvertDao.findBy("fatherQipuId", fatherQipuId);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ProgramAdvert findAdvertById(long id) {
        return programAdvertDao.get(id);
    }

    @Override
    public long saveAdvert(ProgramAdvert programAdvert) {
        programAdvertDao.saveOnly(programAdvert);
        return programAdvert.getId();
    }

    @Override
    public void editAdvert(ProgramAdvert programAdvert) {
        programAdvertDao.save(programAdvert);
    }

    @Override
    public void updateDBAdvert(ProgramData programData) {
        Criteria criteria = programAdvertDao.createCriteria();
        criteria.add(Restrictions.eq("fatherQipuId", programData.getQipuId()));
        criteria.add(Restrictions.eq("advertType", 1));
        List<ProgramAdvert> list = programAdvertDao.find(criteria);
        ProgramAdvert advert = null;
        if (list.size() == 0) {
            advert = new ProgramAdvert();
            advert.setFatherQipuId(programData.getQipuId());
            advert.setAdvertType(1);
            advert.setUuid(UUID.randomUUID().toString());
            programAdvertDao.saveOnly(advert);
        }
    }

    @Override
    public void updateSnapPicUrl(long id, String url) {
        String hql = "update ProgramData set snapPicUrl = ? , sync = 0 where id =" + id;
        int executeNum = programDataDao.createQuery(hql).setString(0, url).executeUpdate();
        logger.info("programId={},executeNum={},snapPicUrl={}", id, executeNum, url);
    }

    @Override
    public List<Long> findChangeTagProgramIds() {
        List<Long> list = null;
        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append("select program.id pid FROM live_episode program,  channel_base channel");
        sqlBuffer.append(" WHERE channel.live_type = 2 ");
        sqlBuffer.append(" AND channel.is_enable != -1 ");
        sqlBuffer.append(" AND channel.live_type = 2 ");
        sqlBuffer.append(" AND program.father_id = channel.id ");
        sqlBuffer.append(" AND program.is_delete = 0");
        sqlBuffer.append(" AND program.program_tag is not null ");
        sqlBuffer.append(" AND program.stop_play_time > ADDDATE(now(),-5) ");
        sqlBuffer.append(" AND program.start_play_time <  ADDDATE( now() , INTERVAL -channel.max_playback_period SECOND ) ");
        sqlBuffer.append(" AND program.program_tag != '200003919_200978719' ");
        try {
            list = programDataDao.getSession().createSQLQuery(sqlBuffer.toString()).addScalar("pid", new LongType()).list();
        } catch (Exception e) {
            list = new ArrayList<Long>();
            logger.error(" findChangeTagProgramIds ", e);
        }
        return list;
    }

    @Override
    public long saveOAData(IqiyiOAData data) {
        oaDataDao.saveOnly(data);
        return data.getId();
    }

    @Override
    public void updateDocEditStatusByDocNo(IqiyiOAData data, int episodeGrade) {
        String sql = "update ProgramData set oaDocEditorStatus = ?,episodeGrade=? where oa_doc_no = ?";
        int executeUpdate = programDataDao.getSession().createQuery(sql)
                .setString(0, data.getChiefEditorApprovalStatus())
                .setInteger(1, episodeGrade)
                .setString(2, data.getDocNo()).executeUpdate();
        logger.info("[updateDocEditStatusByDocNo][entityId={}][docNo={}][episodeGrade={}][docEditorStatus={}][executeUpdate={}]", data.getId(), data.getDocNo(), episodeGrade, data.getChiefEditorApprovalStatus(), executeUpdate);
    }

    @Override
    public void updateDocEditStatusByDocNo(IqiyiOAData data) {
        String sql = "update ProgramData set oaDocEditorStatus = ? where oa_doc_no = ?";
        int executeUpdate = programDataDao.getSession().createQuery(sql)
                .setString(0, data.getChiefEditorApprovalStatus())
                .setString(1, data.getDocNo()).executeUpdate();
        logger.info("[updateDocEditStatusByDocNo][entityId={}][docNo={}][docEditorStatus={}][executeUpdate={}]", data.getId(), data.getDocNo(), data.getChiefEditorApprovalStatus(), executeUpdate);

    }


    @Override
    public List<ProgramData> checkFeedListQuery(long minStartTime, long maxStartTime) {
        StringBuffer sbuffer = new StringBuffer("select program from ProgramData program,ChannelBase channel where program.fatherId = channel.id ");
        sbuffer.append(" and channel.isEnable != -1 ");
        sbuffer.append(" and channel.liveType = 2 ");
        sbuffer.append(" and program.startPlayTime >= '" + DateTimeUtil.transLongFormat(minStartTime) + "'");
        sbuffer.append(" and program.startPlayTime <= '" + DateTimeUtil.transLongFormat(maxStartTime) + "'");
        sbuffer.append(" order by program.startPlayTime asc ");
        Query query = programDataDao.createQuery(sbuffer.toString());
        List<ProgramData> programDataList = query.list();
        return programDataList;
    }

    @Override
    public void doCheckClearFeedById(long programId) {
        ProgramData programData = programDataDao.get(programId);
        doCheckClearFeedByQipuId(programData.getQipuId());
    }

    @Override
    public void doCheckClearFeedByQipuId(long programQipuId) {
        String sql = "update FeedData set offLine = 1 where programQipuId = ? and status = 0";
        int executeUpdate = feedDataDao.getSession().createQuery(sql)
                .setLong(0, programQipuId).executeUpdate();
        logger.info("[doCheckClearFeedByQipuId][qipuId={}][executeUpdate={}]", programQipuId, executeUpdate);
    }

    @Override
    public void addFeedData(FeedData feedData) {
        feedDataDao.saveOnly(feedData);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<FeedData> findFeedData(List<Criterion> cList) {
        Criteria criteria = feedDataDao.createCriteria();
        for (Criterion temp : cList) {
            criteria.add(temp);
        }
        List<FeedData> list = feedDataDao.find(criteria);
        return list;
    }

    @Override
    public void batchUpdateFeedDataList(List<FeedData> dataList) {
        for (FeedData data : dataList) {
            feedDataDao.save(data);
        }
    }

}
